package Thread.ConnectionPool;

import com.sun.corba.se.spi.ior.iiop.IIOPFactories;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

/**
 * @author VX5
 * @Title: MJC
 * @ProjectName DataStructure
 * @Description: TODO
 * @date ${DAT}9:34
 */
public class ConnectionPool {
    private LinkedList<Connection> pool = new LinkedList<Connection>();

    public ConnectionPool(int intialSize){
        if (intialSize > 0){
            for (int i = 0;i < intialSize; i++){
                pool.addLast(ConnectionDriver.createConnection());
            }
        }
    }

    public void releaseConnection(Connection connection){
        if (connection!=null){
            synchronized (pool){//连接释放后需要进行通知，这样其他消费者能够感知到连接池中已经归还了一个链接
                pool.addLast(connection);
                pool.notifyAll();;
            }
        }
    }

    //获取连接
    public Connection fetchConnection(long mills) throws InterruptedException {
        synchronized (pool){
            if (mills<0){
                while (pool.isEmpty()){
                    pool.wait();
                }
                return pool.removeFirst();
            }else {
                long future = System.currentTimeMillis() + mills;
                long remaining = mills;
                while (pool.isEmpty() && remaining > 0){
                    pool.wait(remaining);
                    remaining = future - System.currentTimeMillis();
                }
                Connection result = null;
                if (!pool.isEmpty()){
                    result = pool.removeFirst();
                }
                return result;
            }
        }
    }

    static public class ConnectionDriver{
        static class ConnectionHandler implements InvocationHandler{
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (method.getName().equals("commit")){
                    TimeUnit.MILLISECONDS.sleep(100);
                }
                return null;
            }
        }

        //创建一个Connection代理，在commit时休眠100毫秒
        public static final Connection createConnection(){
            Connection connection = (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(),new Class<?>[]{Connection.class},new ConnectionHandler());
            return connection;
        }
    }
}
